package com.xinghanlaser.applet.base.common.controller;

import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xinghanlaser.applet.base.common.entity.ResponseEntity;
import com.xinghanlaser.applet.base.common.exception.ServiceException;
import com.xinghanlaser.applet.base.common.vo.PageVO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;

/**
 * Created by yyym on 2019/9/21.
 */
@Slf4j
@Validated
public abstract class BaseController<E, T extends Serializable> {

    public abstract String getIdColumn();
    public abstract IService<E> getService();

    @GetMapping("common/list")
    @ApiOperation("通用接口：按条件查询记录列表")
    public ResponseEntity<List<E>> list(E t) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>(t);
        return ResponseEntity.ok(getService().list(queryWrapper));
    }

    @GetMapping("common/page")
    @ApiOperation("通用接口：按条件查询分页")
    public ResponseEntity<ResponseEntity.PageResult<E>> page(E t, PageVO pageVo) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>(t).orderByDesc(getIdColumn());
        IPage<E> pageResult = getService().page(new Page<>(pageVo.getPage(), pageVo.getSize()), queryWrapper);
        return ResponseEntity.okPage(pageResult);
    }

    @GetMapping("common/{id}")
    @ApiOperation("通用接口：根据ID查询单个")
    public ResponseEntity<E> get(@PathVariable("id") T id) {
        return Optional.ofNullable(getService().getById(id))
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.faultMsg("ID不存在"));
    }

    @PostMapping("common")
    @ApiOperation("通用接口：新增或者修改数据")
    public final ResponseEntity<Void> postOrPut(@RequestBody @Valid E t) {
        try {
            getService().saveOrUpdate(t);
        } catch (DuplicateKeyException e) {
            log.error("新增/修改异常,存在重复值:entity={}", t, e);
            return ResponseEntity.faultMsg("新增异常,存在重复数据");
        } catch (Exception e) {
            log.error("新增/修改异常:entity={}", t, e);
            return ResponseEntity.faultMsg("新增/修改异常");
        }
        return ResponseEntity.okMsg("新增/修改成功");
    }


    @DeleteMapping("common/{id}")
    @ApiOperation("通用接口：根据ID删除单个")
    public ResponseEntity<Void> delete(@PathVariable("id") T id) {
        try {
            getService().removeById(id);
        } catch (Exception e) {
            log.error("删除异常:id={}", id, e);
            return ResponseEntity.faultMsg("删除异常");
        }
        return ResponseEntity.okMsg("删除成功");
    }

    @PutMapping("common/del-batch")
    @ApiOperation("通用接口：批量删除")
    @DSTransactional
    public ResponseEntity<Void> deleteBatch(@RequestBody @NotEmpty(message = "至少选中一个条目进行删除") List<T> ids) {
        try {
            getService().removeByIds(ids);
        } catch (Exception e) {
            log.error("批量删除异常:ids={}", ids, e);
            return ResponseEntity.faultMsg("批量删除异常");
        }
        return ResponseEntity.okMsg("批量删除成功");
    }
}
